﻿//  -------------------- iSharePoint -------------------- //
// 
//  Company:	IT Complex, LLC
//  Project:	Smart.Common
//  File name:	WebEntityMapper.cs
//  Developer:	Solomatov Igor
//  Created:	15.04.2012
// 
//  -------------------- iSharePoint -------------------- //

#define FAST_MAPPER

using Smart.Common.Entities.Mapper;

namespace Smart.Common.Entities
{
	public class WebEntityMapper : EntityMapper
	{
		public static WebEntityMapper Current = new WebEntityMapper();

#if FAST_MAPPER
		public override MapperClassBuilderConfig GetConfig()
		{
			var config = new MapperClassBuilderConfig
							{
								Usings = "using Microsoft.SharePoint;\r\nusing Smart.Common.Entities;",
								SourceType = "SPListItem"
							};

			config.FillTempls[FieldMappingType.Identifier] = "e.{0} = Identifier.Empty;";
			config.FillTempls[FieldMappingType.String] = "e.{0} = null;";
			config.FillTempls[FieldMappingType.DateTime] = "e.{0} = DateTime.MinValue;";
			config.FillTempls[FieldMappingType.Int] = "e.{0} = 0;";
			config.FillTempls[FieldMappingType.Double] = "e.{0} = 0;";
			config.FillTempls[FieldMappingType.Bool] = "e.{0} = false;";
			config.FillTempls[FieldMappingType.Lookup] = "e.{0} = new LookupValue(Identifier.Empty);";
			config.FillTempls[FieldMappingType.LookupMulti] = "e.{0} = new LookupValueCollection();";
			config.FillTempls[FieldMappingType.User] = "e.{0} = new UserValue(Identifier.Empty);";
			config.FillTempls[FieldMappingType.UserMulti] = "e.{0} = new UserValueCollection();";
			config.FillTempls[FieldMappingType.Link] = "e.{0} = new LinkValue(null, null);";
			config.FillTempls[FieldMappingType.ChoiceMulti] = "e.{0} = new ChoiceValueCollection();";

			config.PreLoad = "\t\t\tstring tmp;";
			config.LoadTempls[FieldMappingType.Identifier] = "e.{0} = (Identifier)SPH.GetItemValueInt(s, \"{1}\");";
			config.LoadTempls[FieldMappingType.String] = "e.{0} = SPH.GetItemValueStr(s, \"{1}\");";
			config.LoadTempls[FieldMappingType.DateTime] = "e.{0} = SPH.GetItemValueDT(s, \"{1}\");";
			config.LoadTempls[FieldMappingType.Int] = "e.{0} = SPH.GetItemValueInt(s, \"{1}\");";
			config.LoadTempls[FieldMappingType.Double] = "e.{0} = SPH.GetItemValueDbl(s, \"{1}\");";
			config.LoadTempls[FieldMappingType.Bool] = "e.{0} = SPH.GetItemValueBool(s, \"{1}\");";
			config.LoadTempls[FieldMappingType.Lookup] =
				"tmp = SPH.GetItemValueStr(s, \"{1}\"); e.{0} = (tmp.IsNullOrEmpty() ? new LookupValue(Identifier.Empty) : new SPFieldLookupValue(tmp).CvtL());";
			config.LoadTempls[FieldMappingType.LookupMulti] =
				"tmp = SPH.GetItemValueStr(s, \"{1}\"); e.{0} = (tmp.IsNullOrEmpty() ? new LookupValueCollection() : new SPFieldLookupValueCollection(tmp).CvtL());";
			config.LoadTempls[FieldMappingType.User] = "tmp = SPH.GetItemValueStr(s, \"{1}\"); e.{0} = (tmp.IsNullOrEmpty() ? new UserValue(Identifier.Empty) : new SPFieldLookupValue(tmp).CvtU());";
			config.LoadTempls[FieldMappingType.UserMulti] =
				"tmp = SPH.GetItemValueStr(s, \"{1}\"); e.{0} = (tmp.IsNullOrEmpty() ? new UserValueCollection() : new SPFieldLookupValueCollection(tmp).CvtU());";
			config.LoadTempls[FieldMappingType.Link] = "tmp = SPH.GetItemValueStr(s, \"{1}\"); e.{0} = (tmp.IsNullOrEmpty() ? new LinkValue(null, null) : new SPFieldUrlValue(tmp).CvtL());";
			config.LoadTempls[FieldMappingType.ChoiceMulti] =
				"tmp = SPH.GetItemValueStr(s, \"{1}\"); e.{0} = (tmp.IsNullOrEmpty() ? new ChoiceValueCollection() : new SPFieldMultiChoiceValue(tmp).CvtC());";
			config.PostLoad = "\t\t\te.IsNew = (s.ID == 0);";

			config.SaveTempls[FieldMappingType.Identifier] = "s[\"{1}\"] = e.{0}.Int;";
			config.SaveTempls[FieldMappingType.String] = "s[\"{1}\"] = e.{0};";
			config.SaveTempls[FieldMappingType.DateTime] = "s[\"{1}\"] = (e.{0} == DateTime.MinValue ? null : (object)e.{0});";
			config.SaveTempls[FieldMappingType.Int] = "s[\"{1}\"] = e.{0};";
			config.SaveTempls[FieldMappingType.Double] = "s[\"{1}\"] = e.{0};";
			config.SaveTempls[FieldMappingType.Bool] = "s[\"{1}\"] = e.{0};";
			config.SaveTempls[FieldMappingType.Lookup] = "s[\"{1}\"] = e.{0}.ID.Int;";
			config.SaveTempls[FieldMappingType.LookupMulti] = "s[\"{1}\"] = e.{0}.ToString();";
			config.SaveTempls[FieldMappingType.User] = "s[\"{1}\"] = e.{0}.ID.Int;";
			config.SaveTempls[FieldMappingType.UserMulti] = "s[\"{1}\"] = e.{0}.ToString();";
			config.SaveTempls[FieldMappingType.Link] = "s[\"{1}\"] = e.{0}.ToString();";
			config.SaveTempls[FieldMappingType.ChoiceMulti] = "s[\"{1}\"] = e.{0}.ToString();";
			config.PostSave =
				"\t\t\tif (e.IsNew)\r\n\t\t\t{\t\t\t\tvar ei = EntityFactory.QueryEntity(e.GetType());\r\n\t\t\t\tif (ei != null && !ei.ContentType.IsNullOrEmpty())\r\n\t\t\t\t\tif (ei.ContentType.IsContentTypeId()) s[SPBuiltInFieldId.ContentTypeId] = new SPContentTypeId(ei.ContentType); else s[SPBuiltInFieldId.ContentType] = ei.ContentType;\r\n\t\t\t}";

			return config;
		}
#else
		public override bool LoadEntity(object source, Entity entity)
		{
			var s = source as SPListItem;

			if (s == null)
				throw new ArgumentException();

			var et = entity.GetType();

			var typeName = et.FullName;

			var mapping = ReadCache(typeName, et);

			foreach (var fmi in mapping)
			{
				if (fmi.Direction == FieldMappingDirection.Out)
					continue;

				string tmp;

				switch (fmi.MappingType)
				{
					case FieldMappingType.Identifier:
						fmi.Property.SetValue(entity, (Identifier)SPH.GetItemValueInt(s, \"{1}\"), null);
						break;

					case FieldMappingType.String:
						fmi.Property.SetValue(entity, SPH.GetItemValueStr(s, \"{1}\"), null);
						break;

					case FieldMappingType.DateTime:
						fmi.Property.SetValue(entity, SPH.GetItemValueDT(s, \"{1}\"), null);
						break;

					case FieldMappingType.Int:
						fmi.Property.SetValue(entity, SPH.GetItemValueInt(s, \"{1}\"), null);
						break;

					case FieldMappingType.Double:
						fmi.Property.SetValue(entity, SPH.GetItemValueDbl(s, \"{1}\"), null);
						break;

					case FieldMappingType.Bool:
						fmi.Property.SetValue(entity, SPH.GetItemValueBool(s, \"{1}\"), null);
						break;

					case FieldMappingType.Lookup:
						tmp = SPH.GetItemValueStr(s, \"{1}\");
						fmi.Property.SetValue(entity, (tmp.IsNullOrEmpty() ? new LookupValue(Identifier.Empty) : new SPFieldLookupValue(tmp).CvtL()), null);
						break;

					case FieldMappingType.LookupMulti:
						tmp = SPH.GetItemValueStr(s, \"{1}\");
						fmi.Property.SetValue(entity, (tmp.IsNullOrEmpty() ? new LookupValueCollection() : new SPFieldLookupValueCollection(tmp).CvtL()), null);
						break;

					case FieldMappingType.User:
						tmp = SPH.GetItemValueStr(s, \"{1}\");
						fmi.Property.SetValue(entity, (tmp.IsNullOrEmpty() ? new UserValue(Identifier.Empty) : new SPFieldLookupValue(tmp).CvtU()), null);
						break;

					case FieldMappingType.UserMulti:
						tmp = SPH.GetItemValueStr(s, \"{1}\");
						fmi.Property.SetValue(entity, (tmp.IsNullOrEmpty() ? new UserValueCollection() : new SPFieldLookupValueCollection(tmp).CvtU()), null);
						break;

					case FieldMappingType.Link:
						tmp = SPH.GetItemValueStr(s, \"{1}\");
						fmi.Property.SetValue(entity, (tmp.IsNullOrEmpty() ? new LinkValue(null, null) : new SPFieldUrlValue(tmp).CvtL()), null);
						break;

					case FieldMappingType.ChoiceMulti:
						tmp = SPH.GetItemValueStr(s, \"{1}\");
						fmi.Property.SetValue(entity, (tmp.IsNullOrEmpty() ? new ChoiceValueCollection() : new SPFieldMultiChoiceValue(tmp).CvtC()), null);
						break;

					default:
						throw new NotSupportedException();
				}
			}

			return true;
		}

		public override bool SaveEntity(Entity entity, object source)
		{
			var s = source as SPListItem;

			if (s == null)
				throw new ArgumentException();

			var et = entity.GetType();

			var typeName = et.FullName;

			var mapping = ReadCache(typeName, et);

			foreach (var fmi in mapping)
			{
				if (fmi.Direction == FieldMappingDirection.In)
					continue;

				switch (fmi.MappingType)
				{
					case FieldMappingType.Identifier:
						SPH.SetItemValue(s, \"{1}\", ((Identifier)fmi.Property.GetValue(entity, null)).Int);
						break;

					case FieldMappingType.String:
						SPH.SetItemValue(s, \"{1}\", fmi.Property.GetValue(entity, null));
						break;

					case FieldMappingType.DateTime:
						SPH.SetItemValue(s, \"{1}\", fmi.Property.GetValue(entity, null));
						break;

					case FieldMappingType.Int:
						SPH.SetItemValue(s, \"{1}\", fmi.Property.GetValue(entity, null));
						break;

					case FieldMappingType.Double:
						SPH.SetItemValue(s, \"{1}\", fmi.Property.GetValue(entity, null));
						break;

					case FieldMappingType.Bool:
						SPH.SetItemValue(s, \"{1}\", fmi.Property.GetValue(entity, null));
						break;

					case FieldMappingType.Lookup:
						SPH.SetItemValue(s, \"{1}\", ((LookupValue)fmi.Property.GetValue(entity, null)).ID.Int);
						break;

					case FieldMappingType.LookupMulti:
						SPH.SetItemValue(s, \"{1}\", ((LookupValueCollection)fmi.Property.GetValue(entity, null)).ToString());
						break;

					case FieldMappingType.User:
						SPH.SetItemValue(s, \"{1}\", ((UserValue)fmi.Property.GetValue(entity, null)).ID.Int);
						break;

					case FieldMappingType.UserMulti:
						SPH.SetItemValue(s, \"{1}\", ((UserValueCollection)fmi.Property.GetValue(entity, null)).ToString());
						break;

					case FieldMappingType.Link:
						SPH.SetItemValue(s, \"{1}\", ((LinkValue)fmi.Property.GetValue(entity, null)).ToString());
						break;

					case FieldMappingType.ChoiceMulti:
						SPH.SetItemValue(s, \"{1}\", ((ChoiceValueCollection)fmi.Property.GetValue(entity, null)).ToString());
						break;

					default:
						throw new NotSupportedException();
				}
			}

			if (entity.IsNew)
			{
				var ei = EntityFactory.QueryEntity(et);

				if (ei != null && !ei.ContentType.IsNullOrEmpty())
					s[SPBuiltInFieldId.ContentType] = ei.ContentType;
			}

			return true;
		}
#endif
	}
}